const isEventProp = (key) => key.startsWith("on");
const getEventName = (key) => key.slice(2).toLowerCase();

const h = (tag, props, children) => {
  return {
    tag,
    props,
    children,
  };
};

const mount = (vNode, container) => {
  const el = (vNode.el = document.createElement(vNode.tag));

  if (vNode.props) {
    for (const [key, value] of Object.entries(vNode.props)) {
      if (isEventProp(key)) {
        el.addEventListener(getEventName(key), value);
      } else {
        el.setAttribute(key, value);
      }
    }
  }

  if (vNode.children) {
    if (typeof vNode.children === "string") {
      el.textContent = vNode.children;
    } else {
      vNode.children.forEach((child) => mount(child, el));
    }
  }

  container.appendChild(el);
};

const patch = (n1, n2) => {
  // 如果n1 n2 类型不一样，直接替换
  if (n1.tag !== n2.tag) {
    const n1ElParent = n1.el.parentElement;
    n1ElParent.removeChild(n1.el);
    mount(n2, n1ElParent);
  } else {
    // 如果类型一样，先处理 props，在处理 children
    const el = (n2.el = n1.el);

    const oldProps = n1.props || {};
    const newProps = n2.props || {};
    // 将新的 props 添加到 el 上
    for (const key in newProps) {
      const oldValue = oldProps[key];
      const newValue = newProps[key];
      if (newValue !== oldValue) {
        if (isEventProp(key)) {
          el.addEventListener(getEventName(key), newValue);
        } else {
          el.setAttribute(key, newValue);
        }
      }
    }
    // 删除旧的 props
    for (const key in oldProps) {
      if (isEventProp(key)) {
        el.removeEventListener(getEventName(key), oldProps[key]);
      }
      if (!(key in newProps)) {
        el.removeAttribute(key);
      }
    }
    // 处理 children
    const oldChildren = n1.children || [];
    const newChildren = n2.children || [];
    // 情况一：newChildren 是个 string
    if (typeof newChildren === "string") {
      // 边界情况
      if (typeof oldChildren === "string") {
        if (newChildren !== oldChildren) {
          el.textContent = newChildren;
        }
      } else {
        el.innerHTML = newChildren;
      }
    } else {
      // 情况二：newChildren 是数组
      if (typeof oldChildren === "string") {
        el.innerHTML = "";
        newChildren.forEach((child) => mount(child, el));
      } else {
        // oldChildren: [v1, v2, v3, v8, v9]
        // newChildren: [v1, v5, v6]
        // 取两者的最小长度
        const commonLength = Math.min(newChildren.length, oldChildren.length);
        for (let i = 0; i < commonLength; i++) {
          // 前面相同索引的 vnode,进行patch操作 patch(v1,v1) patch(v2,v5) patch(v3,v6)
          patch(oldChildren[i], newChildren[i]);
        }
        // oldChildren: [v1, v2, v3]
        // newChildren: [v1, v5, v6, v8, v9]
        if (newChildren.length > oldChildren.length) {
          newChildren.slice(commonLength).forEach((child) => mount(child, el));
        }
        // oldChildren: [v1, v2, v3, v8, v9]
        // newChildren: [v1, v5, v6]
        if (newChildren.length < oldChildren.length) {
          oldChildren.slice(commonLength).forEach((child) => {
            el.removeChild(child.el);
          });
        }
      }
    }
  }
};
